package com.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;

/**
 * 日期处理
 */
public class DateUtils {
    private final static Logger logger = LoggerFactory.getLogger(DateUtils.class);
    /**
     * 时间格式(yyyy-MM-dd)
     */
    public final static String DATE_PATTERN = "yyyy-MM-dd";
    /**
     * 时间格式(yyyy-MM-dd HH:mm:ss)
     */
    public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    public final static String DAY_DATA = "yyyy-MM-dd 00:00:00";

    public final static String DAY_HOUR_DATA = "MM-dd";

    public static final String yyyyMMdd = "yyyyMMdd";

    public static final String yyyyMMddHH = "yyyyMMddHH";

    public static final String yyyyMMddHHmm = "yyyyMMddHHmm";

    public static final String HOUR_DATA = "yyyy-MM-dd HH:00:00";

    public static final String MINUTE_DATA = "yyyy-MM-dd HH:mm:00";

    public static final String DAY_END = "yyyy-MM-dd 23:59:59";

    public static String format(Date date) {
        return format(date, DATE_PATTERN);
    }

    public static Date getHourDateByTime(Date logTime) {
        return DateUtils.parse(DateUtils.format(logTime, "yyyyMMddHH"), "yyyyMMddHH");
    }

    public static Date plusOneHour(Date date) {
        return new Date(date.getTime() + 3600000);
    }

    public static Date beforeOneHour(Date date) {
        return new Date(date.getTime() - 3600000);
    }

    public static Date beforeDay(Date date, int days) {
        return plusDay(date, 0 - days);
    }

    public static Date beforeMin(Date date, int min) {
        return new Date(date.getTime() - min * 60000);
    }

    public static Date getDayByTime(Date logTime) {
        return DateUtils.parse(DateUtils.format(logTime, "yyyyMMdd"), "yyyyMMdd");
    }

    public static String format(Date date, String pattern) {
        if (date != null) {
            SimpleDateFormat df = new SimpleDateFormat(pattern);
            return df.format(date);
        }
        return null;
    }

    public static Date parse(String timeStr, String pattern) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        try {
            return simpleDateFormat.parse(timeStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Date convertTime(Date date, String pattern) {
        return parse(format(date, pattern), pattern);
    }

    /**
     * 计算距离现在多久，非精确
     *
     * @param date
     * @return
     */
    public static String getTimeBefore(Date date) {
        Date now = new Date();
        long l = now.getTime() - date.getTime();
        long day = l / (24 * 60 * 60 * 1000);
        long hour = (l / (60 * 60 * 1000) - day * 24);
        long min = ((l / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long s = (l / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
        String r = "";
        if (day > 0) {
            r += day + "天";
        } else if (hour > 0) {
            r += hour + "小时";
        } else if (min > 0) {
            r += min + "分";
        } else if (s > 0) {
            r += s + "秒";
        }
        r += "前";
        return r;
    }

    /**
     * 计算距离现在多久，精确
     *
     * @param date
     * @return
     */
    public static String getTimeBeforeAccurate(Date date) {
        Date now = new Date();
        long l = now.getTime() - date.getTime();
        long day = l / (24 * 60 * 60 * 1000);
        long hour = (l / (60 * 60 * 1000) - day * 24);
        long min = ((l / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long s = (l / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
        String r = "";
        if (day > 0) {
            r += day + "天";
        }
        if (hour > 0) {
            r += hour + "小时";
        }
        if (min > 0) {
            r += min + "分";
        }
        if (s > 0) {
            r += s + "秒";
        }
        r += "前";
        return r;
    }

    /**
     * 获得当天零时零分零秒
     *
     * @return
     */
    public static Date initDateByDay() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    public static Date plusDay(Date date, int days) {
        return new Date(date.getTime() + 86400000 * days);
    }

    public static Date plusOneDay(Date date) {
        return plusDay(date, 1);
    }

    public static String getYesterday() {
        return getAppointday(1, DATE_PATTERN);
    }

    /**
     * 获得指定日期零时零分零秒
     *
     * @return
     */
    public static String getAppointday(int number, String pattern) {
        Calendar c = Calendar.getInstance();
        int day1 = c.get(Calendar.DATE);
        c.set(Calendar.DATE, day1 - number);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        return format(c.getTime(), pattern);
    }

    public static String getNowDayFormat() {
        return format(new Date(), yyyyMMdd);
    }

    public static String getNowSecondFormat() {
        return format(new Date(), DATE_TIME_PATTERN);
    }

    public static String getNowTimeFormat() {
        return format(new Date(), DATE_TIME_PATTERN);
    }

    public static int getCurrentDayOfWeek(Date date) {
        int day = getWeek(date);
        switch (day) {
            case Calendar.MONDAY:
                return 0;
            case Calendar.TUESDAY:
                return 1;
            case Calendar.WEDNESDAY:
                return 2;
            case Calendar.THURSDAY:
                return 3;
            case Calendar.FRIDAY:
                return 4;
            case Calendar.SATURDAY:
                return 5;
            case Calendar.SUNDAY:
                return 6;
            default:
                return day;
        }
    }

    public static int getWeek(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.DAY_OF_WEEK);
    }

    // 创建指定日期的指定小时结束时刻的Date对象（小时:59:59）
    public static Date createHourDate(Date date, int hour, int minute, int second) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, hour);
        cal.set(Calendar.MINUTE, minute);
        cal.set(Calendar.SECOND, second);
        return cal.getTime();
    }

    public static Date plusSecond(Date date, int second) {
        return new Date(date.getTime() + second * 1000);
    }

    public static Date getMinTime(Date startTime, Date entTime) {
        return startTime.getTime() > entTime.getTime() ? entTime : startTime;
    }

    public static int getHour(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.HOUR_OF_DAY);
    }

    public static Date getMaxTime(Date startTime, Date entTime) {
        return startTime.getTime() > entTime.getTime() ? startTime : entTime;
    }

    public static Date plusMin(Date date, int min) {
        return new Date(date.getTime() + min * 60000);
    }

    public static Date getMinuteByTime(Date logTime) {
        return DateUtils.parse(DateUtils.format(logTime, "yyyyMMdd HH:mm"), "yyyyMMdd HH:mm");
    }

    /**
     * 计算指定日期加减天数后的日期
     *
     * @param date 原始日期（java.util.Date）
     * @param days 天数（正数：加天数；负数：减天数）
     * @return 计算后的日期（java.util.Date）
     */
    public static Date plusDays(Date date, int days) {
        // 校验输入：若date为null，默认用当前日期
        if (date == null) {
            date = new Date();
        }
        // 1. 将 Date 转换为 LocalDate（Java 8 日期类，更易用）
        LocalDate localDate = date.toInstant()
                .atZone(ZoneId.systemDefault())  // 转换为系统默认时区的日期
                .toLocalDate();
        // 2. 加减天数（支持负数：如-3表示减3天）
        LocalDate resultLocalDate = localDate.plusDays(days);
        // 3. 将 LocalDate 转回 Date
        return Date.from(resultLocalDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

    public static long getDaysBetween(Date startDate, Date endDate) {
        if (startDate == null || endDate == null) {
            throw new IllegalArgumentException("日期参数不能为空");
        }

        // 清除时间部分，只比较日期
        Calendar startCal = Calendar.getInstance();
        startCal.setTime(startDate);
        startCal.set(Calendar.HOUR_OF_DAY, 0);
        startCal.set(Calendar.MINUTE, 0);
        startCal.set(Calendar.SECOND, 0);
        startCal.set(Calendar.MILLISECOND, 0);

        Calendar endCal = Calendar.getInstance();
        endCal.setTime(endDate);
        endCal.set(Calendar.HOUR_OF_DAY, 0);
        endCal.set(Calendar.MINUTE, 0);
        endCal.set(Calendar.SECOND, 0);
        endCal.set(Calendar.MILLISECOND, 0);

        long diffMillis = endCal.getTimeInMillis() - startCal.getTimeInMillis();
        return diffMillis / (1000 * 60 * 60 * 24);
    }

    public static long getSecondsToTodayEnd() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        long endTimeMillis = calendar.getTimeInMillis();
        long currentTimeMillis = System.currentTimeMillis();
        return (endTimeMillis - currentTimeMillis) / 1000;
    }
}
